/*
 * Adapted from package com.codeshogun.android.shakesample.ShakeActivity
 */

package edu.gmu.swe632.fruit.service;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import edu.gmu.swe632.fruit.activity.AutoSosActivity;

public class AutoSosService extends Service implements SensorEventListener
{
	public static final String MOTION = "edu.gmu.swe632.fruit.activity.AutoSosService.motion";
	public static boolean isTriggered;

	private static final String TAG = "sosservice";

	// For shake motion detection.
	private SensorManager sensorMgr;
	private long lastUpdate = -1;
	private float x, y, z;
	private float last_x, last_y, last_z;
	private static final int MOTION_THRESHOLD = 100;
	private static final long AUTO_TIMEOUT = 60000;
	private Timer timer;
	private final IBinder mBinder = new LocalBinder();

	@Override
	public void onCreate()
	{
		super.onCreate();

		Log.d(TAG, "onCreate");

		// start motion detection
		sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
		Sensor sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		boolean accelSupported = sensorMgr.registerListener(this, sensor,
				SensorManager.SENSOR_DELAY_GAME);

		// No accelerometer on this device
		if (!accelSupported)
			sensorMgr.unregisterListener(this);

		timer = new Timer();
		timer.schedule(new LocalTimerTask(), AUTO_TIMEOUT);
	}

	@Override
	public void onDestroy()
	{
		super.onDestroy();

		Log.d(TAG, "onDestroy");

		timer.cancel();
		timer = null;
		sensorMgr.unregisterListener(this);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		super.onStartCommand(intent, flags, startId);

		Log.d(TAG, "Its going to be sticky");
		return START_STICKY;
	}

	@Override
	public IBinder onBind(Intent intent)
	{
		return mBinder;
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy)
	{
	}

	@Override
	public void onSensorChanged(SensorEvent event)
	{
		Sensor sensor = event.sensor;
		float[] values = event.values;

		if (sensor.getType() == Sensor.TYPE_ACCELEROMETER)
		{
			long curTime = System.currentTimeMillis();
			// only allow one update every 100ms.
			if ((curTime - lastUpdate) > 100)
			{
				long diffTime = (curTime - lastUpdate);
				lastUpdate = curTime;

				x = values[SensorManager.DATA_X];
				y = values[SensorManager.DATA_Y];
				z = values[SensorManager.DATA_Z];

				float speed = Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000;

				if (speed > MOTION_THRESHOLD)
				{
					restartTimer();

					if (isTriggered)
					{
						Bundle bundle = new Bundle();
						bundle.putInt(MOTION, 1);

						Intent intent = new Intent(getBaseContext(), AutoSosActivity.class)
								.putExtras(bundle);
						intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
						intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
						getApplication().startActivity(intent);
					}

					// Log.d(TAG, "shake detected w/ speed: " + speed);
				}

				last_x = x;
				last_y = y;
				last_z = z;
			}
		}
	}

	private void restartTimer()
	{
		timer.cancel();
		timer = new Timer();
		timer.schedule(new LocalTimerTask(), AUTO_TIMEOUT);
	}

	public class LocalBinder extends Binder
	{
		public AutoSosService getService()
		{
			return AutoSosService.this;
		}
	}

	private class LocalTimerTask extends TimerTask
	{
		@Override
		public void run()
		{
			Log.d(TAG, "I've been still for a minute!!!");

			if (!isTriggered)
			{
				Log.d(TAG, "I'm triggering a new intent.");

				Intent intent = new Intent(getBaseContext(), AutoSosActivity.class);
				intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
				getApplication().startActivity(intent);
			}

			restartTimer();
		}
	}
}
